home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / cctools / as / m98k.c < prev    next >
C/C++ Source or Header  |  1993-09-09  |  42KB  |  1,700 lines

  1. #include <ctype.h>
  2. #include <string.h>
  3. #include <mach-o/m98k/reloc.h>
  4. #include "m98k-opcode.h"
  5. #include "as.h"
  6. #include "flonum.h"
  7. #include "expr.h"
  8. #include "hash.h"
  9. #include "read.h"
  10. #include "md.h"
  11. #include "obstack.h"
  12. #include "symbols.h"
  13. #include "messages.h"
  14. #include "atof-ieee.h"
  15. #include "input-scrub.h"
  16. #include "sections.h"
  17.  
  18.  
  19. /*
  20.  * These are the default cputype and cpusubtype for the m98k architecture.
  21.  */
  22. const cpu_type_t md_cputype = CPU_TYPE_MC98000;
  23. cpu_subtype_t md_cpusubtype = CPU_SUBTYPE_MC98000_ALL;
  24.  
  25. /* This is the byte sex for the m98k architecture */
  26. const enum byte_sex md_target_byte_sex = BIG_ENDIAN_BYTE_SEX;
  27.  
  28. /* These characters start a comment anywhere on the line */
  29. const char md_comment_chars[] = ";";
  30.  
  31. /* These characters only start a comment at the beginning of a line */
  32. const char md_line_comment_chars[] = "#";
  33.  
  34. /*
  35.  * These characters can be used to separate mantissa decimal digits from 
  36.  * exponent decimal digits in floating point numbers.
  37.  */
  38. const char md_EXP_CHARS[] = "eE";
  39.  
  40. /*
  41.  * The characters after a leading 0 that means this number is a floating point
  42.  * constant as in 0f123.456 or 0d1.234E-12 (see md_EXP_CHARS above).
  43.  */
  44. const char md_FLT_CHARS[] = "dDfF";
  45.  
  46. /*
  47.  * This is the machine dependent pseudo opcode table for this target machine.
  48.  */
  49. static void s_reg(
  50.     int reg);
  51. const pseudo_typeS md_pseudo_table[] =
  52. {
  53.     {"greg", s_reg, 'r' },
  54.     {0} /* end of table marker */
  55. };
  56.  
  57. #define RT(x)           (((x) >> 21) & 0x1f)
  58. #define RA(x)           (((x) >> 16) & 0x1f)
  59.  
  60. struct m98k_insn {
  61.     unsigned long opcode;
  62.     expressionS exp;
  63.     enum reloc_type_m98k reloc;
  64.     long pcrel;
  65.     long pcrel_reloc;
  66. };
  67.  
  68. /*
  69.  * The pointer to the opcode hash table built by md_begin() and used by
  70.  * md_assemble() to look up opcodes.
  71.  */
  72. static struct hash_control *op_hash = NULL;
  73.  
  74. /*
  75.  * These aid in the printing of better error messages for parameter syntax
  76.  * errors when there is only one mnemonic in the tables.
  77.  */
  78. static unsigned long error_param_count = 0;
  79. static char *error_param_message = NULL;
  80.  
  81. /*
  82.  * These are name names of the known special registers and the numbers assigned
  83.  * to them.
  84.  */
  85. struct special_register {
  86.     unsigned long number;
  87.     char *name;
  88. };
  89. static const struct special_register special_registers[] = {
  90.     { 0,   "mq" }, /* 601 only */
  91.     { 1,   "xer" },
  92.     { 4,   "rtcu" },
  93.     { 5,   "rtcl" },
  94.     { 8,   "lr" },
  95.     { 9,   "ctr" },
  96.     { 18,  "dsisr" },
  97.     { 19,  "dar" },
  98.     { 22,  "dec" },
  99.     { 25,  "sdr1" },
  100.     { 26,  "srr0" },
  101.     { 27,  "srr1" },
  102.     { 272, "sprg0" },
  103.     { 273, "sprg1" },
  104.     { 274, "sprg2" },
  105.     { 275, "sprg3" },
  106.     { 280, "asr" },
  107.     { 281, "rtcd" },
  108.     { 282, "rtci" },
  109.     { 287, "pvr" },
  110.     { 528, "ibat0u" },
  111.     { 529, "ibat0l" },
  112.     { 530, "ibat1u" },
  113.     { 531, "ibat1l" },
  114.     { 532, "ibat2u" },
  115.     { 533, "ibat2l" },
  116.     { 534, "ibat3u" },
  117.     { 535, "ibat3l" },
  118.     { 528, "bat0u" }, /* 601 only */
  119.     { 529, "bat0l" }, /* 601 only */
  120.     { 530, "bat1u" }, /* 601 only */
  121.     { 531, "bat1l" }, /* 601 only */
  122.     { 532, "bat2u" }, /* 601 only */
  123.     { 533, "bat2l" }, /* 601 only */
  124.     { 534, "bat3u" }, /* 601 only */
  125.     { 535, "bat3l" }, /* 601 only */
  126.     { 536, "dbat0u" },
  127.     { 537, "dbat0l" },
  128.     { 538, "dbat1u" },
  129.     { 539, "dbat1l" },
  130.     { 540, "dbat2u" },
  131.     { 541, "dbat2l" },
  132.     { 542, "dbat3u" },
  133.     { 543, "dbat3l" },
  134.     { 1008,"hid0" }, /* 601 only */
  135.     { 1009,"hid1" }, /* 601 only */
  136.     { 1010,"hid2" }, /* 601 only */
  137.     { 1013,"hid5" }, /* 601 only */
  138.     { 1013,"dabr" }, /* 601 only */
  139.     { 1022,"fpecr" },
  140.     { 1023,"pid" }, /* 601 only */
  141.     { 0, "" } /* end of table marker */
  142. };
  143.  
  144. /*
  145.  * These are name names of the condition field special registers and the
  146.  * numbers assigned to them.
  147.  */
  148. struct condition_symbol {
  149.     unsigned long value;
  150.     char *name;
  151. };
  152. static const struct condition_symbol condition_symbols[] = {
  153.     { 0, "lt" }, /* less than */
  154.     { 1, "gt" }, /* greater than */
  155.     { 2, "eq" }, /* equal */
  156.     { 3, "so" }, /* summary overflow */
  157.     { 3, "un" }, /* unordered */
  158.     { 0, "" } /* end of table marker */
  159. };
  160.  
  161. struct CR_field {
  162.     unsigned long value;
  163.     char *name;
  164. };
  165. static const struct CR_field CR_fields[] = {
  166.     { 0,  "cr0" }, /* CR field 0 */
  167.     { 4,  "cr1" }, /* CR field 1 */
  168.     { 8,  "cr2" }, /* CR field 2 */
  169.     { 12, "cr3" }, /* CR field 3 */
  170.     { 16, "cr4" }, /* CR field 4 */
  171.     { 20, "cr5" }, /* CR field 5 */
  172.     { 24, "cr6" }, /* CR field 6 */
  173.     { 28, "cr7" }, /* CR field 7 */
  174.     { 0, "" } /* end of table marker */
  175. };
  176.  
  177. /*
  178.  * These are built in macros because they are trivial to implement as macros
  179.  * which otherwise be less obvious to do special entries for them.
  180.  */
  181. struct macros {
  182.     char *name;
  183.     char *body;
  184. };
  185. static const struct macros m98k_macros[] = {
  186.     { "extldi\n",  "rldicr $0,$1,$3,$2-1\n" },
  187.     { "extldi.\n", "rldicr. $0,$1,$3,$2-1\n" },
  188.     { "extrdi\n",  "rldicl $0,$1,$2+$3,64-$2\n" },
  189.     { "extrdi.\n", "rldicl. $0,$1,$2+$3,64-$2\n" },
  190.     { "insrdi\n",  "rldimi $0,$1,64-($3+$2),$3\n" },
  191.     { "insrdi.\n", "rldimi. $0,$1,64-($3+$2),$3\n" },
  192.     { "rotldi\n",  "rldicl $0,$1,$2,0\n" },
  193.     { "rotldi.\n", "rldicl. $0,$1,$2,0\n" },
  194.     { "rotrdi\n",  "rldicl $0,$1,64-$2,0\n" },
  195.     { "rotrdi.\n", "rldicl. $0,$1,64-$2,0\n" },
  196.     { "rotld\n",   "rldcl $0,$1,$2,0\n" },
  197.     { "rotld.\n",  "rldcl. $0,$1,$2,0\n" },
  198.     { "sldi\n",    "rldicr $0,$1,$2,63-$2\n" },
  199.     { "sldi.\n",   "rldicr. $0,$1,$2,63-$2\n" },
  200.     { "srdi\n",    "rldicl $0,$1,64-$2,$2\n" },
  201.     { "srdi.\n",   "rldicl. $0,$1,64-$2,$2\n" },
  202.     { "clrldi\n",  "rldicl $0,$1,0,$2\n" },
  203.     { "clrldi.\n", "rldicl. $0,$1,0,$2\n" },
  204.     { "clrrdi\n",  "rldicl $0,$1,0,63-$2\n" },
  205.     { "clrrdi.\n", "rldicl. $0,$1,0,63-$2\n" },
  206.     { "clrlsldi\n","rldic $0,$1,$3,$2-$3\n" },
  207.     { "clrlsldi.\n","rldic. $0,$1,$3,$2-$3\n" },
  208.  
  209.     { "extlwi\n",  "rlwinm $0,$1,$3,0,$2-1\n" },
  210.     { "extlwi.\n", "rlwinm. $0,$1,$3,0,$2-1\n" },
  211.     { "extrwi\n",  "rlwinm $0,$1,$2+$3,32-$2,31\n" },
  212.     { "extrwi.\n", "rlwinm. $0,$1,$2+$3,32-$2,31\n" },
  213.     { "inslwi\n",  "rlwimi $0,$1,32-$3,$3,($3+$2)-1\n" },
  214.     { "inslwi.\n", "rlwimi. $0,$1,32-$3,$3,($3+$2)-1\n" },
  215.     { "insrwi\n",  "rlwimi $0,$1,32-($3+$2),$3,($3+$2)-1\n" },
  216.     { "insrwi.\n", "rlwimi. $0,$1,32-($3+$2),$3,($3+$2)-1\n" },
  217.     { "rotlwi\n",  "rlwinm $0,$1,$2,0,31\n" },
  218.     { "rotlwi.\n", "rlwinm. $0,$1,$2,0,31\n" },
  219.     { "rotrwi\n",  "rlwinm $0,$1,32-$2,0,31\n" },
  220.     { "rotrwi.\n", "rlwinm. $0,$1,32-$2,0,31\n" },
  221.     { "rotlw\n",   "rlwnm $0,$1,$2,0,31\n" },
  222.     { "rotlw.\n",  "rlwnm. $0,$1,$2,0,31\n" },
  223.     { "slwi\n",    "rlwinm $0,$1,$2,0,31-$2\n" },
  224.     { "slwi.\n",   "rlwinm. $0,$1,$2,0,31-$2\n" },
  225.     { "srwi\n",    "rlwinm $0,$1,32-$2,$2,31\n" },
  226.     { "srwi.\n",   "rlwinm. $0,$1,32-$2,$2,31\n" },
  227.     { "clrlwi\n",  "rlwinm $0,$1,0,$2,31\n" },
  228.     { "clrlwi.\n", "rlwinm. $0,$1,0,$2,31\n" },
  229.     { "clrrwi\n",  "rlwinm $0,$1,0,0,31-$2\n" },
  230.     { "clrrwi.\n", "rlwinm. $0,$1,0,0,31-$2\n" },
  231.     { "clrlslwi\n","rlwinm $0,$1,$3,$2-$3,31-$2\n" },
  232.     { "clrlslwi.\n","rlwinm. $0,$1,$3,$2-$3,31-$2\n" },
  233.  
  234.     { "mtxer\n",   "mtspr 1,$0\n"},
  235.     { "mfxer\n",   "mfspr $0,1\n"},
  236.     { "mtlr\n",    "mtspr 8,$0\n"},
  237.     { "mflr\n",    "mfspr $0,8\n"},
  238.     { "mtctr\n",   "mtspr 9,$0\n"},
  239.     { "mfctr\n",   "mfspr $0,9\n"},
  240.     { "mtdsisr\n", "mtspr 18,$0\n"},
  241.     { "mfdsisr\n", "mfspr $0,18\n"},
  242.     { "mtdar\n",   "mtspr 19,$0\n"},
  243.     { "mfdar\n",   "mfspr $0,19\n"},
  244.     { "mtdec\n",   "mtspr 22,$0\n"},
  245.     { "mfdec\n",   "mfspr $0,22\n"},
  246.     { "mtsdr1\n",  "mtspr 25,$0\n"},
  247.     { "mfsdr1\n",  "mfspr $0,25\n"},
  248.     { "mtsrr0\n",  "mtspr 26,$0\n"},
  249.     { "mfsrr0\n",  "mfspr $0,26\n"},
  250.     { "mtsrr1\n",  "mtspr 27,$0\n"},
  251.     { "mfsrr1\n",  "mfspr $0,27\n"},
  252.     { "mtsprg\n",  "mtspr 272+$0,$1\n"},
  253.     { "mfsprg\n",  "mfspr $0,272+$1\n"},
  254.     { "mtasr\n",   "mtspr 280,$0\n"},
  255.     { "mfasr\n",   "mfspr $0,280\n"},
  256.     { "mtrtcd\n",  "mtspr 281,$0\n"},
  257.     { "mfrtcd\n",  "mfspr $0,281\n"},
  258.     { "mtrtci\n",  "mtspr 282,$0\n"},
  259.     { "mfrtci\n",  "mfspr $0,282\n"},
  260.     { "mfpvr\n",   "mfspr $0,287\n"},
  261.     { "mtibatu\n", "mtspr 528+2*$0,$1\n"},
  262.     { "mfibatu\n", "mfspr $0,528+2*$1\n"},
  263.     { "mtibatl\n", "mtspr 529+2*$0,$1\n"},
  264.     { "mfibatl\n", "mfspr $0,529+2*$1\n"},
  265.     { "mtdbatu\n", "mtspr 536+2*$0,$1\n"},
  266.     { "mfdbatu\n", "mfspr $0,536+2*$1\n"},
  267.     { "mtdbatl\n", "mtspr 537+2*$0,$1\n"},
  268.     { "mfdbatl\n", "mfspr $0,537+2*$1\n"},
  269.  
  270.     { "mtbatu\n",  "mtspr 528+2*$0,$1\n"},
  271.     { "mfbatu\n",  "mfspr $0,528+2*$1\n"},
  272.     { "mtbatl\n",  "mtspr 529+2*$0,$1\n"},
  273.     { "mfbatl\n",  "mfspr $0,529+2*$1\n"},
  274.  
  275.     { "subi\n",    "addi $0,$1,-($2)\n"},
  276.     { "subis\n",   "addis $0,$1,-($2)\n"},
  277.     { "subic\n",   "addic $0,$1,-($2)\n"},
  278.     { "subic.\n",  "addic. $0,$1,-($2)\n"},
  279.  
  280.     {  "", "" } /* end of table marker */
  281. };
  282.  
  283. static int calcop(
  284.     struct m98k_opcode *format,
  285.     char *param,
  286.     struct m98k_insn *insn,
  287.     char *op,
  288.     char prediction);
  289. static char *parse_branch(
  290.     char *param,
  291.     struct m98k_insn *insn,
  292.     struct m98k_opcode *format,
  293.     int parcnt);
  294. static char *parse_displacement(
  295.     char *param,
  296.     struct m98k_insn *insn,
  297.     struct m98k_opcode *format,
  298.     int parcnt);
  299. static char *parse_immediate(
  300.     char *param,
  301.     struct m98k_insn *insn,
  302.     struct m98k_opcode *format,
  303.     int parcnt);
  304. static char *parse_reg(
  305.     char *reg_name,
  306.     char *param,
  307.     struct m98k_insn *insn,
  308.     struct m98k_opcode *format,
  309.     unsigned long parcnt);
  310. static char *parse_spreg(
  311.     char *param,
  312.     struct m98k_insn *insn,
  313.     struct m98k_opcode *format,
  314.     unsigned long parcnt);
  315. static char *parse_bcnd(
  316.     char *param,
  317.     struct m98k_insn *insn,
  318.     struct m98k_opcode *format,
  319.     unsigned long parcnt);
  320. static char *parse_crf(
  321.     char *param,
  322.     struct m98k_insn *insn,
  323.     struct m98k_opcode *format,
  324.     unsigned long parcnt);
  325. static char *parse_num(
  326.     char *param,
  327.     struct m98k_insn *insn,
  328.     struct m98k_opcode *format,
  329.     unsigned long parcnt,
  330.     long max_width_zero);
  331. static char *parse_sh(
  332.     char *param,
  333.     struct m98k_insn *insn,
  334.     struct m98k_opcode *format,
  335.     unsigned long parcnt);
  336. static char *parse_mb(
  337.     char *param,
  338.     struct m98k_insn *insn,
  339.     struct m98k_opcode *format,
  340.     unsigned long parcnt);
  341.  
  342. /*
  343.  * md_begin() is called from main() in as.c before assembly begins.  It is used
  344.  * to allow target machine dependent initialization.
  345.  */
  346. void
  347. md_begin(void)
  348. {
  349.     unsigned long i;
  350.     char *name, *retval;
  351.  
  352.     /* initialize the opcode hash table */
  353.     op_hash = hash_new();
  354.     if(op_hash == NULL)
  355.         as_fatal("Could not initialize the opcode hash table");
  356.  
  357.     /* loop until you see the end of the list */
  358.     i = 0;
  359.     while(*m98k_opcodes[i].name){
  360.         name = m98k_opcodes[i].name;
  361.  
  362.         /* hash each mnemonic and record its position */
  363.         retval = hash_insert(op_hash, name, (char *)&m98k_opcodes[i]);
  364.         if(retval != NULL && *retval != '\0')
  365.         as_fatal("Can't hash instruction '%s':%s",
  366.              m98k_opcodes[i].name, retval);
  367.  
  368.         /* skip to next unique mnemonic or end of list */
  369.         for(i++; strcmp(m98k_opcodes[i].name, name) == 0; i++)
  370.         ;
  371.     }
  372.  
  373.     /*
  374.      * Load the builtin macros for extended mnemonics for rotate and
  375.      * shift mnemonics.
  376.      */
  377.     for(i = 0; *m98k_macros[i].name != '\0'; i++){
  378.         input_line_pointer = m98k_macros[i].name;
  379.         s_macro(0);
  380.         add_to_macro_definition(m98k_macros[i].body);
  381.         s_endmacro(0);
  382.     }
  383. }
  384.  
  385. /*
  386.  * md_end() is called from main() in as.c after assembly ends.  It is used
  387.  * to allow target machine dependent clean up.
  388.  */
  389. void
  390. md_end(void)
  391. {
  392. }
  393.  
  394. /*
  395.  * md_parse_option() is called from main() in as.c to parse target machine
  396.  * dependent command line options.  This routine returns 0 if it is passed an
  397.  * option that is not recognized non-zero otherwise.
  398.  */
  399. int
  400. md_parse_option(
  401. char **argP,
  402. int *cntP,
  403. char ***vecP)
  404. {
  405.     return(0);
  406. }
  407.  
  408. /*
  409.  * s_reg() is used to implement ".greg symbol,exp" and ".xreg symbol,exp"
  410.  * which set symbol to 1 or 0 depending on if the expression is a general
  411.  * register or extended register respectfully.  These are intended for use in
  412.  * macros.
  413.  */
  414. static
  415. void
  416. s_reg(
  417. int reg)
  418. {
  419.     char *name, *end_name, delim;
  420.     symbolS *symbolP;
  421.     unsigned long n_value, val;
  422.  
  423.     if( * input_line_pointer == '"')
  424.       name = input_line_pointer + 1;
  425.     else
  426.       name = input_line_pointer;
  427.     delim = get_symbol_end();
  428.     end_name = input_line_pointer;
  429.     *end_name = delim;
  430.     SKIP_WHITESPACE();
  431.     if ( * input_line_pointer != ',' ) {
  432.         *end_name = 0;
  433.         as_warn("Expected comma after name \"%s\"", name);
  434.         *end_name = delim;
  435.         ignore_rest_of_line();
  436.         return;
  437.     }
  438.     input_line_pointer ++;
  439.     *end_name = 0;
  440.  
  441.     SKIP_WHITESPACE();
  442.     n_value = 0;
  443.     if (*input_line_pointer == reg || *input_line_pointer == toupper(reg)){
  444.         input_line_pointer++;
  445.         if(isdigit(*input_line_pointer)){
  446.         val = 0;
  447.         while (isdigit(*input_line_pointer)){
  448.             if ((val = val * 10 + *input_line_pointer++ - '0') > 31)
  449.             break;
  450.         }
  451.         SKIP_WHITESPACE();
  452.         if(val <= 31 &&
  453.            (*input_line_pointer == '\n' || *input_line_pointer == '@'))
  454.             n_value = 1;
  455.         }
  456.     }
  457.  
  458.     symbolP = symbol_find_or_make (name);
  459.     symbolP -> sy_type = N_ABS;
  460.     symbolP -> sy_other = 0; /* NO_SECT */
  461.     symbolP -> sy_value = n_value;
  462.     symbolP -> sy_frag = & zero_address_frag;
  463.  
  464.     *end_name = delim;
  465.     totally_ignore_line();
  466. }
  467.  
  468. /*
  469.  * md_assemble() is passed a pointer to a string that should be a assembly
  470.  * statement for the target machine.
  471.  */
  472. void
  473. md_assemble(
  474. char *op)
  475. {
  476.     char *param, *thisfrag, prediction;
  477.     struct m98k_opcode *format;
  478.     struct m98k_insn insn;
  479.     unsigned long retry;
  480.  
  481.     /*
  482.      * Pick up the instruction and any trailing branch prediction character
  483.      * (a trailing '+' or '-' on the instruction).
  484.        */
  485.     prediction = '\0';
  486.     for(param = op; !isspace(*param) && *param != '\0' ; param++)
  487.         prediction = *param;
  488.     if(prediction == '+' || prediction == '-')
  489.         param[-1] = '\0';
  490.     else
  491.         prediction = '\0';
  492.     if(*param != '\0')
  493.         *param++ = '\0';
  494.  
  495.     /* try to find the instruction in the hash table */
  496.     if((format = (struct m98k_opcode *)hash_find(op_hash, op)) == NULL){
  497.         as_warn("Invalid mnemonic '%s'", op);
  498.         return;
  499.     }
  500.  
  501.     /* try parsing this instruction into insn */
  502.     retry = 0;
  503.     error_param_count = 0;
  504.     error_param_message = NULL;
  505.     while(calcop(format, param, &insn, op, prediction) == 0){
  506.         /* if it doesn't parse try the next instruction */
  507.         if(strcmp(format->name, format[1].name) == 0){
  508.         format++;
  509.         retry = 1;
  510.         }
  511.         else{
  512.         if(retry == 0){
  513.             if(error_param_message != NULL)
  514.             as_warn(error_param_message, error_param_count + 1);
  515.             else
  516.             as_warn("Parameter syntax error (parameter %lu)",
  517.                 error_param_count + 1);
  518.         }
  519.         else
  520.             as_warn("Parameter syntax error");
  521.         return;
  522.         }
  523.     }
  524.  
  525.     /*
  526.      * Check for invalid forms of instructions.  For the following
  527.      * instructions: lbzu, lbzux, lhzu, lhzux, lhau, lhaux, lwzu, lwzux,
  528.      * lwaux, ldu, ldux
  529.      * if RA == 0 or RA == RT the instruction form is invalid.
  530.      */
  531.     if((insn.opcode & 0xfc000000) == 0x8c000000 || /* lbzu */
  532.        (insn.opcode & 0xfc0007fe) == 0x7c0000ee || /* lbzux */
  533.        (insn.opcode & 0xfc000000) == 0xa4000000 || /* lhzu */
  534.        (insn.opcode & 0xfc0007fe) == 0x7c00026e || /* lbzux */
  535.        (insn.opcode & 0xfc000000) == 0xac000000 || /* lhau */
  536.        (insn.opcode & 0xfc0007fe) == 0x7c0002ee || /* lhaux */
  537.        (insn.opcode & 0xfc000000) == 0x84000000 || /* lwzu */
  538.        (insn.opcode & 0xfc0007fe) == 0x7c00006e || /* lwzux */
  539.        (insn.opcode & 0xfc0007fe) == 0x7c0002ea || /* lwaux */
  540.        (insn.opcode & 0xfc000000) == 0xe8000000 || /* ldu */
  541.        (insn.opcode & 0xfc0007fe) == 0x7c00006a){  /* ldux */
  542.         if(RA(insn.opcode) == 0)
  543.         as_warn("Invalid form of the instruction (RA must not be 0)");
  544.         if(RA(insn.opcode) == RT(insn.opcode))
  545.         as_warn("Invalid form of the instruction (RA must not the same "
  546.             "as RT)");
  547.     }
  548.     /*
  549.      * For the following instructions: stbu, stbux, sthu, sthux, stwu,
  550.      * stwux, stdu, stdux, lfsu, lfsux, lfdu, lfdux, stfsu, stfsux, stfdu,
  551.      * stfdux
  552.      * if RA == 0 the instruction form is invalid.
  553.      */
  554.     if((insn.opcode & 0xfc000000) == 0x9c000000 || /* stbu */
  555.        (insn.opcode & 0xfc0007fe) == 0x7c0001ee || /* stbux */
  556.        (insn.opcode & 0xfc000000) == 0xb4000000 || /* sthu */
  557.        (insn.opcode & 0xfc0007fe) == 0x7c00036e || /* sthux */
  558.        (insn.opcode & 0xfc000000) == 0x94000000 || /* stwu */
  559.        (insn.opcode & 0xfc0007fe) == 0x7c00016e || /* stwux */
  560.        (insn.opcode & 0xfc000003) == 0xf8000001 || /* stdu */
  561.        (insn.opcode & 0xfc0007fe) == 0x7c00016a || /* stdux */
  562.        (insn.opcode & 0xfc000000) == 0xc4000000 || /* lfsu */
  563.        (insn.opcode & 0xfc0007fe) == 0x7c00046e || /* lfsux */
  564.        (insn.opcode & 0xfc000000) == 0xcc000000 || /* lfdu */
  565.        (insn.opcode & 0xfc0007fe) == 0x7c0004ee || /* lfdux */
  566.        (insn.opcode & 0xfc000000) == 0xd4000000 || /* stfsu */
  567.        (insn.opcode & 0xfc0007fe) == 0x7c00056e || /* stfsux */
  568.        (insn.opcode & 0xfc000000) == 0xdc000000 || /* stfdu */
  569.        (insn.opcode & 0xfc0007fe) == 0x7c0005ee){  /* stfdux */
  570.         if(RA(insn.opcode) == 0)
  571.         as_warn("Invalid form of the instruction (RA must not be 0)");
  572.     }
  573.     /*
  574.      * For the following instructions: lmw, lmd, lswi, lswx
  575.      * if RA is in the range of registers to be loaded or RT == RA == 0
  576.      * the instruction form is invalid.  WHAT does this mean?
  577.      */
  578.     if((insn.opcode & 0xfc000000) == 0xb8000000 || /* lmw */
  579.        (insn.opcode & 0xfc000003) == 0xe8000003 || /* lmw */
  580.        (insn.opcode & 0xfc0007fe) == 0x7c0004aa || /* lswi */
  581.        (insn.opcode & 0xfc0007fe) == 0x7c00042a){  /* lswx */
  582.     }
  583.  
  584.     /* grow the current frag and plop in the opcode */
  585.     thisfrag = frag_more(4);
  586.     md_number_to_chars(thisfrag, insn.opcode, 4);
  587.  
  588.     /*
  589.      * If the -g flag is present generate a line number stab for the
  590.      * instruction.
  591.      * 
  592.      * See the detailed comments about stabs in read_a_source_file() for a
  593.      * description of what is going on here.
  594.      */
  595.     if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){
  596.         (void)symbol_new(
  597.           "",
  598.           68 /* N_SLINE */,
  599.           text_nsect,
  600.           logical_input_line /* n_desc, line number */,
  601.           obstack_next_free(&frags) - frag_now->fr_literal,
  602.           frag_now);
  603.     }
  604.  
  605.     /* if this instruction requires labels mark it for later */
  606.     switch(insn.reloc){
  607.     case NO_RELOC:
  608.         break;
  609.     case M98K_RELOC_HI16:
  610.     case M98K_RELOC_LO16:
  611.     case M98K_RELOC_HA16:
  612.     case M98K_RELOC_LO14:
  613.         fix_new(frag_now,
  614.             thisfrag - frag_now->fr_literal,
  615.             4,
  616.             insn.exp.X_add_symbol,
  617.             insn.exp.X_subtract_symbol,
  618.             insn.exp.X_add_number,
  619.             0, 0,
  620.             insn.reloc);
  621.         break;
  622.     case M98K_RELOC_BR14:
  623.         fix_new(frag_now,
  624.             thisfrag - frag_now->fr_literal,
  625.             4,
  626.             insn.exp.X_add_symbol,
  627.             insn.exp.X_subtract_symbol,
  628.             insn.exp.X_add_number,
  629.             insn.pcrel,
  630.             insn.pcrel_reloc,
  631.             insn.reloc);
  632.         break;
  633.  
  634.     case M98K_RELOC_BR24:
  635.         fix_new(frag_now,
  636.             thisfrag - frag_now->fr_literal,
  637.             4,
  638.             insn.exp.X_add_symbol,
  639.             insn.exp.X_subtract_symbol,
  640.             insn.exp.X_add_number,
  641.             insn.pcrel,
  642.             insn.pcrel_reloc,
  643.             insn.reloc);
  644.         break;
  645.     default:
  646.         as_warn("Unknown relocation type");
  647.         break;
  648.     }
  649. }
  650.  
  651. static
  652. int
  653. calcop(
  654. struct m98k_opcode *format,
  655. char *param,
  656. struct m98k_insn *insn,
  657. char *op,
  658. char prediction)
  659. {
  660.     unsigned long parcnt;
  661.  
  662.     /* initial the passed structure */
  663.     memset(insn, '\0', sizeof(struct m98k_insn));
  664.     insn->opcode = format->opcode;
  665.     insn->reloc = NO_RELOC;
  666.  
  667.     /* parse all parameters */
  668.     for(parcnt = 0; parcnt < 5 &&
  669.             format->ops[parcnt].type != NONE; parcnt++){
  670.         error_param_count = parcnt;
  671.  
  672.         switch(format->ops[parcnt].type){
  673.         case PCREL:
  674.         case BADDR:
  675.         param = parse_branch(param, insn, format, parcnt);
  676.         break;
  677.         case D:
  678.         case DS:
  679.         param = parse_displacement(param, insn, format, parcnt);
  680.         break;
  681.         case SI:
  682.         case UI:
  683.         param = parse_immediate(param, insn, format, parcnt);
  684.         break;
  685.         case GREG:
  686.         case G0REG:
  687.         param = parse_reg("r", param, insn, format, parcnt);
  688.         break;
  689.         case FREG:
  690.         param = parse_reg("f", param, insn, format, parcnt);
  691.         break;
  692.         case SGREG:
  693.         param = parse_reg("sr", param, insn, format, parcnt);
  694.         break;
  695.         case SPREG:
  696.         param = parse_spreg(param, insn, format, parcnt);
  697.         break;
  698.         case BCND:
  699.         param = parse_bcnd(param, insn, format, parcnt);
  700.         break;
  701.         case CRF:
  702.         case CRFONLY:
  703.         param = parse_crf(param, insn, format, parcnt);
  704.         break;
  705.         case NUM:
  706.         param = parse_num(param, insn, format, parcnt, 0);
  707.         break;
  708.         case NUM0:
  709.         param = parse_num(param, insn, format, parcnt, 1);
  710.         break;
  711.         case sh:
  712.         param = parse_sh(param, insn, format, parcnt);
  713.         break;
  714.         case mb:
  715.         param = parse_mb(param, insn, format, parcnt);
  716.         break;
  717.         default:
  718.         as_fatal("Unknown parameter type");
  719.         }
  720.  
  721.         /* see if parser failed or not */
  722.         if (param == NULL)
  723.         return(0);
  724.     }
  725.     if(format->ops[0].type == NONE && *param != '\0'){
  726.         error_param_message = "too many parameters";
  727.         return(0);
  728.     }
  729.  
  730.     if(IS_BRANCH_CONDITIONAL(insn->opcode)){
  731.         if(prediction != '\0'){
  732.         /*
  733.          * Set the Y_BIT assuming the displacement is non-negitive.
  734.          * If the displacement is negitive then the Y_BIT is flipped
  735.          * in md_number_to_imm().
  736.          */
  737.         if(prediction == '+')
  738.             insn->opcode |= Y_BIT;
  739.         else{ /* prediction == '-' */
  740.             if((insn->opcode & Y_BIT) != 0)
  741.             as_warn("branch prediction ('-') ignored (specified "
  742.                 "operand has prediction bit set)");
  743.             else
  744.             insn->opcode &= ~(Y_BIT);
  745.         }
  746.         }
  747.     }
  748.     else{
  749.         if(prediction != '\0')
  750.         as_warn("branch prediction ignored (instruction is not a "
  751.             "conditional branch)");
  752.     }
  753.     return(1);
  754. }
  755.  
  756. static
  757. char *
  758. parse_displacement(
  759. char *param,
  760. struct m98k_insn *insn,
  761. struct m98k_opcode *format,
  762. int parcnt)
  763. {
  764.     unsigned long val;
  765.     char *end, *saveptr, *saveparam;
  766.     segT seg;
  767.  
  768.  
  769.     if(parcnt != 1 || format->ops[2].type != G0REG)
  770.          as_fatal("internal error, bad table entry for instruction %s "
  771.               "(displacement operand not second operand or general "
  772.               "register not third operand)", format->name);
  773.  
  774.     /*
  775.      * There must be "(rX)" (where X is a number between 0-31) or "(0)"
  776.      * at the end of the parameter string.  To know out where the
  777.      * displacement expression ends determine the begining the "(rX)"
  778.      * by looking for the last '(' in the string.  The parsing of this
  779.      * trailing string will be done in another routine.
  780.      */
  781.     end = strrchr(param, '(');
  782.     if(end == NULL)
  783.         return(NULL);
  784.     *end = '\0';
  785.  
  786.     /*
  787.      * The expression may have one of the following: hi16(exp), ha16(exp),
  788.      * or lo16(exp) around the expression which determines the relocation
  789.      * type.
  790.      */
  791.     if(strncmp(param,"hi16(",5) == 0){
  792.         insn->reloc = M98K_RELOC_HI16;
  793.         param += 5;
  794.     }
  795.     else if(strncmp(param,"ha16(",5) == 0){
  796.         insn->reloc = M98K_RELOC_HA16;
  797.         param += 5;
  798.     }
  799.     else if(strncmp(param,"lo16(",5) == 0){
  800.         if(format->ops[parcnt].type == DS)
  801.         insn->reloc = M98K_RELOC_LO14;
  802.         else
  803.         insn->reloc = M98K_RELOC_LO16;
  804.         param += 5;
  805.     }
  806.  
  807.     saveptr = input_line_pointer;
  808.     input_line_pointer = param;
  809.  
  810.     seg = expression(&insn->exp);
  811.     try_to_make_absolute(&insn->exp);
  812.     seg = insn->exp.X_seg;
  813.  
  814.     saveparam = input_line_pointer;
  815.     input_line_pointer = saveptr;
  816.     *end = '(';
  817.  
  818.     if(insn->reloc != NO_RELOC){
  819.         if(*saveparam != ')' || ++saveparam != end)
  820.         return(NULL);
  821.     }
  822.     else{
  823.         if(saveparam != end)
  824.         return(NULL);
  825.         val = insn->exp.X_add_number;
  826.         if(seg != SEG_ABSOLUTE){
  827.         error_param_message = "Parameter error: expression must be "
  828.                       "absolute (parameter %lu)";
  829.         return(NULL);
  830.         }
  831.         if(val & 0x8000){
  832.         if((val & 0xffff0000) != 0xffff0000){
  833.             error_param_message = "Parameter error: expression out of "
  834.                       "range (parameter %lu)";
  835.             return(NULL);
  836.         }
  837.         val = val & 0xffff;
  838.         }
  839.         else{
  840.         if((val & 0xffff0000) != 0){
  841.             error_param_message = "Parameter error: expression out of "
  842.                       "range (parameter %lu)";
  843.             return(NULL);
  844.         }
  845.         }
  846.         if(format->ops[parcnt].type == DS){
  847.         if((val & 0x3) != 0){
  848.             error_param_message = "Parameter error: expression must be "
  849.                       "a multiple of 4 (parameter %lu)";
  850.             return(NULL);
  851.         }
  852.         val >>= 2;
  853.         }
  854.         insn->opcode |= val << format->ops[parcnt].offset;
  855.     }
  856.     return(saveparam);
  857. }
  858.  
  859. static
  860. char *
  861. parse_immediate(
  862. char *param,
  863. struct m98k_insn *insn,
  864. struct m98k_opcode *format,
  865. int parcnt)
  866. {
  867.     unsigned long val;
  868.     char *saveptr, *saveparam;
  869.     segT seg;
  870.  
  871.     /*
  872.      * The expression may have one of the following: hi16(exp), ha16(exp),
  873.      * or lo16(exp) around the expression which determines the relocation
  874.      * type.
  875.      */
  876.     if(strncmp(param,"hi16(",5) == 0){
  877.         insn->reloc = M98K_RELOC_HI16;
  878.         param += 5;
  879.     }
  880.     else if(strncmp(param,"ha16(",5) == 0){
  881.         insn->reloc = M98K_RELOC_HA16;
  882.         param += 5;
  883.     }
  884.     else if(strncmp(param,"lo16(",5) == 0){
  885.         if(format->ops[parcnt].type == DS)
  886.         insn->reloc = M98K_RELOC_LO14;
  887.         else
  888.         insn->reloc = M98K_RELOC_LO16;
  889.         param += 5;
  890.     }
  891.  
  892.     saveptr = input_line_pointer;
  893.     input_line_pointer = param;
  894.  
  895.     seg = expression(&insn->exp);
  896.     try_to_make_absolute(&insn->exp);
  897.     seg = insn->exp.X_seg;
  898.  
  899.     saveparam = input_line_pointer;
  900.     input_line_pointer = saveptr;
  901.  
  902.     if(insn->reloc != NO_RELOC){
  903.         if(*saveparam != ')')
  904.         return(NULL);
  905.         saveparam++;
  906.         if(*saveparam == '\0'){
  907.         if(parcnt == 4 || format->ops[parcnt+1].type == NONE)
  908.             return(saveparam);
  909.         else
  910.             return(NULL);
  911.         }
  912.         else if(*saveparam == ','){
  913.         if(parcnt != 4 && format->ops[parcnt+1].type != NONE)
  914.             return(saveparam+1);
  915.         else
  916.             return(NULL);
  917.         }
  918.         else
  919.         return(NULL);
  920.     }
  921.     else{
  922.         val = insn->exp.X_add_number;
  923.         if(seg != SEG_ABSOLUTE){
  924.         error_param_message = "Parameter error: expression must be "
  925.                       "absolute (parameter %lu)";
  926.         return(NULL);
  927.         }
  928.         if(format->ops[parcnt].type == SI){
  929.         if(val & 0x8000){
  930.             if((val & 0xffff0000) != 0xffff0000){
  931.             error_param_message = "Parameter error: expression out "
  932.                           "of range (parameter %lu)";
  933.             return(NULL);
  934.             }
  935.             val = val & 0xffff;
  936.         }
  937.         else{
  938.             if((val & 0xffff0000) != 0){
  939.             error_param_message = "Parameter error: expression out "
  940.                           "of range (parameter %lu)";
  941.             return(NULL);
  942.             }
  943.         }
  944.         }
  945.         else{
  946.         if((val & 0xffff0000) != 0){
  947.             error_param_message = "Parameter error: expression out "
  948.                       "of range (parameter %lu)";
  949.             return(NULL);
  950.         }
  951.         }
  952.         if(*saveparam == '\0'){
  953.         if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
  954.             insn->opcode |= val << format->ops[parcnt].offset;
  955.             return(saveparam);
  956.         }
  957.         else
  958.             return(NULL);
  959.         }
  960.         else if(*saveparam == ','){
  961.         if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
  962.             insn->opcode |= val << format->ops[parcnt].offset;
  963.             return(saveparam+1);
  964.         }
  965.         else
  966.             return(NULL);
  967.         }
  968.         else
  969.         return(NULL);
  970.     }
  971.     return(saveparam);
  972. }
  973.  
  974. static
  975. char *
  976. parse_branch(
  977. char *param,
  978. struct m98k_insn *insn,
  979. struct m98k_opcode *format,
  980. int parcnt)
  981. {
  982.     char *saveptr, *saveparam;
  983.     segT seg;
  984.  
  985.     saveptr = input_line_pointer;
  986.     input_line_pointer = param;
  987.  
  988.     seg = expression(&insn->exp);
  989.     try_to_make_absolute(&insn->exp);
  990.     seg = insn->exp.X_seg;
  991.  
  992.     saveparam = input_line_pointer;
  993.     input_line_pointer = saveptr;
  994.  
  995.     insn->pcrel = 0;
  996.     insn->pcrel_reloc = 0;
  997.     if(format->ops[parcnt].type == PCREL){
  998.         /*
  999.          * The NeXT linker has the ability to scatter blocks of
  1000.          * sections between labels.  This requires that brances to
  1001.          * labels that survive to the link phase must be able to
  1002.          * be relocated.
  1003.          */
  1004.         if(insn->exp.X_add_symbol != NULL &&
  1005.            (insn->exp.X_add_symbol->sy_name[0] != 'L' || flagseen ['L']))
  1006.         insn->pcrel_reloc = 1;
  1007.         else
  1008.         insn->pcrel_reloc = 0;
  1009.         insn->pcrel = 1;
  1010.     }
  1011.     switch(format->ops[parcnt].width){
  1012.     case 14:
  1013.         insn->reloc = M98K_RELOC_BR14;
  1014.         break;
  1015.     case 24:
  1016.         insn->reloc = M98K_RELOC_BR24;
  1017.         break;
  1018.     default:
  1019.         as_fatal("Unknown branch instruction width %d",
  1020.             format->ops[parcnt].width);
  1021.         break;
  1022.     }
  1023.     return(saveparam);
  1024. }
  1025.  
  1026. static
  1027. char *
  1028. parse_reg(
  1029. char *reg_name,
  1030. char *param,
  1031. struct m98k_insn *insn,
  1032. struct m98k_opcode *format,
  1033. unsigned long parcnt)
  1034. {
  1035.     unsigned long val, d;
  1036.  
  1037.     d = 0;
  1038.     if(*param == '(' && parcnt == 2 &&
  1039.        (format->ops[1].type == D || format->ops[1].type == DS)){
  1040.         d = 1;
  1041.         param++;
  1042.     }
  1043.  
  1044.     if(format->ops[parcnt].type == G0REG && *param == '0'){
  1045.         val = 0;
  1046.         param++;
  1047.     }
  1048.     else{
  1049.         val = 0;
  1050.         while(*reg_name){
  1051.         if(*param++ != *reg_name++)
  1052.             return(NULL);
  1053.         }
  1054.         if(!isdigit(*param))
  1055.         return(NULL);
  1056.  
  1057.         while(isdigit(*param))
  1058.         if((val = val * 10 + *param++ - '0') >=
  1059.            1 << format->ops[parcnt].width)
  1060.         return(NULL);
  1061.  
  1062.         if(format->ops[parcnt].type == G0REG && val == 0){
  1063.         error_param_message = "Parameter error: r0 not allowed "
  1064.                       "for parameter %lu (code as 0 not r0)";
  1065.         return(NULL);
  1066.         }
  1067.     }
  1068.  
  1069.     if(*param == '\0'){
  1070.         if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
  1071.         insn->opcode |= val << format->ops[parcnt].offset;
  1072.         return(param);
  1073.         }
  1074.         else
  1075.         return(NULL);
  1076.     }
  1077.     else if(*param == ','){
  1078.         if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
  1079.         insn->opcode |= val << format->ops[parcnt].offset;
  1080.         return(param+1);
  1081.         }
  1082.         else
  1083.         return(NULL);
  1084.     }
  1085.     else if(d == 1 && *param == ')' && param[1] == '\0'){
  1086.         if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
  1087.         insn->opcode |= val << format->ops[parcnt].offset;
  1088.         return(++param);
  1089.         }
  1090.         else
  1091.         return(NULL);
  1092.     }
  1093.     return(NULL);
  1094. }
  1095.  
  1096. static
  1097. char *
  1098. parse_spreg(
  1099. char *param,
  1100. struct m98k_insn *insn,
  1101. struct m98k_opcode *format,
  1102. unsigned long parcnt)
  1103. {
  1104.     int val;
  1105.     unsigned long i;
  1106.     char *saveptr, save_c;
  1107.     expressionS exp;
  1108.     segT seg;
  1109.  
  1110.     saveptr = input_line_pointer;
  1111.     input_line_pointer = param;
  1112.     while(*param != ',' && *param != '\0')
  1113.         param++;
  1114.     save_c = *param;
  1115.     *param = '\0';
  1116.  
  1117.     seg = SEG_ABSOLUTE;
  1118.     val = 0;
  1119.     for(i = 0; *special_registers[i].name != '\0'; i++){
  1120.         if(strcmp(input_line_pointer, special_registers[i].name) == 0){
  1121.         val = special_registers[i].number;
  1122.         break;
  1123.         }
  1124.     }
  1125.     if(*special_registers[i].name == '\0'){
  1126.         seg = expression(&exp);
  1127.         try_to_make_absolute(&exp);
  1128.         seg = exp.X_seg;
  1129.         val = exp.X_add_number;
  1130.     }
  1131.     *param = save_c;
  1132.     input_line_pointer = saveptr;
  1133.  
  1134.     if(seg != SEG_ABSOLUTE){
  1135.         error_param_message = "Parameter error: expression must be "
  1136.                   "absolute (parameter %lu)";
  1137.         return(NULL);
  1138.     }
  1139.     if(val > 1024 || val < 0){
  1140.         error_param_message = "Parameter error: expression out "
  1141.                   "of range (parameter %lu)";
  1142.         return(NULL);
  1143.     }
  1144.  
  1145.     val = ((val & 0x1f) << 5) | ((val >> 5) & 0x1f);
  1146.  
  1147.     if(*param == '\0'){
  1148.         if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
  1149.         insn->opcode |= val << format->ops[parcnt].offset;
  1150.         return(param);
  1151.         }
  1152.         else
  1153.         return(NULL);
  1154.     }
  1155.     else if(*param == ','){
  1156.         if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
  1157.         insn->opcode |= val << format->ops[parcnt].offset;
  1158.         return(param+1);
  1159.         }
  1160.         else
  1161.         return(NULL);
  1162.     }
  1163.     return(NULL);
  1164. }
  1165.  
  1166. static
  1167. char *
  1168. parse_bcnd(
  1169. char *param,
  1170. struct m98k_insn *insn,
  1171. struct m98k_opcode *format,
  1172. unsigned long parcnt)
  1173. {
  1174.     int val;
  1175.     unsigned long i, j;
  1176.     char *saveptr, save_c, *plus, save_plus;
  1177.     expressionS exp;
  1178.     segT seg;
  1179.  
  1180.     saveptr = input_line_pointer;
  1181.     input_line_pointer = param;
  1182.     while(*param != ',' && *param != '\0')
  1183.         param++;
  1184.     save_c = *param;
  1185.     *param = '\0';
  1186.  
  1187.     /*
  1188.      * look for "[CR_field+]condition_symbol".
  1189.      */
  1190.     val = -1;
  1191.     for(plus = input_line_pointer; *plus != '+' && *plus != '\0'; plus++)
  1192.         ;
  1193.     if(*plus == '+'){
  1194.         save_plus = *plus;
  1195.         *plus = '\0';
  1196.         for(i = 0; *CR_fields[i].name != '\0'; i++)
  1197.         if(strcmp(input_line_pointer, CR_fields[i].name) == 0)
  1198.             break;
  1199.         *plus = save_plus;
  1200.         if(*CR_fields[i].name != '\0'){
  1201.         for(j = 0; *condition_symbols[j].name != '\0'; j++)
  1202.             if(strcmp(plus+1, condition_symbols[j].name) == 0)
  1203.             break;
  1204.         if(*condition_symbols[j].name != '\0'){
  1205.             val = CR_fields[i].value + condition_symbols[j].value;
  1206.         }
  1207.         }
  1208.     }
  1209.     else{
  1210.         for(i = 0; *condition_symbols[i].name != '\0'; i++)
  1211.         if(strcmp(input_line_pointer, condition_symbols[i].name) == 0)
  1212.             break;
  1213.         if(*condition_symbols[i].name != '\0')
  1214.         val = condition_symbols[i].value;
  1215.     }
  1216.     if(val == -1){
  1217.         seg = expression(&exp);
  1218.         try_to_make_absolute(&exp);
  1219.         seg = exp.X_seg;
  1220.         val = exp.X_add_number;
  1221.         if(seg != SEG_ABSOLUTE){
  1222.         error_param_message = "Parameter error: expression must be "
  1223.                       "absolute (parameter %lu)";
  1224.         *param = save_c;
  1225.         input_line_pointer = saveptr;
  1226.         return(NULL);
  1227.         }
  1228.         if(val >= (1 << format->ops[parcnt].width) || val < 0){
  1229.         error_param_message = "Parameter error: expression out "
  1230.                       "of range (parameter %lu)";
  1231.         *param = save_c;
  1232.         input_line_pointer = saveptr;
  1233.         return(NULL);
  1234.         }
  1235.     }
  1236.  
  1237.     *param = save_c;
  1238.     input_line_pointer = saveptr;
  1239.  
  1240.  
  1241.     if(*param == '\0'){
  1242.         if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
  1243.         insn->opcode |= val << format->ops[parcnt].offset;
  1244.         return(param);
  1245.         }
  1246.         else
  1247.         return(NULL);
  1248.     }
  1249.     else if(*param == ','){
  1250.         if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
  1251.         insn->opcode |= val << format->ops[parcnt].offset;
  1252.         return(param+1);
  1253.         }
  1254.         else
  1255.         return(NULL);
  1256.     }
  1257.     return(NULL);
  1258.  
  1259. }
  1260.  
  1261. static
  1262. char *
  1263. parse_crf(
  1264. char *param,
  1265. struct m98k_insn *insn,
  1266. struct m98k_opcode *format,
  1267. unsigned long parcnt)
  1268. {
  1269.     int val;
  1270.     unsigned long i;
  1271.     char *saveptr, save_c;
  1272.     expressionS exp;
  1273.     segT seg;
  1274.  
  1275.     saveptr = input_line_pointer;
  1276.     input_line_pointer = param;
  1277.     while(*param != ',' && *param != '\0')
  1278.         param++;
  1279.     save_c = *param;
  1280.     *param = '\0';
  1281.     val = -1;
  1282.     for(i = 0; *CR_fields[i].name != '\0'; i++){
  1283.         if(strcmp(input_line_pointer, CR_fields[i].name) == 0){
  1284.         val = CR_fields[i].value;
  1285.         break;
  1286.         }
  1287.     }
  1288.     if(val == -1){
  1289.         if(format->ops[parcnt].type == CRFONLY){
  1290.         *param = save_c;
  1291.         input_line_pointer = saveptr;
  1292.         return(NULL);
  1293.         }
  1294.         seg = expression(&exp);
  1295.         try_to_make_absolute(&exp);
  1296.         seg = exp.X_seg;
  1297.         val = exp.X_add_number;
  1298.         if(seg != SEG_ABSOLUTE){
  1299.         error_param_message = "Parameter error: expression must be "
  1300.                       "absolute (parameter %lu)";
  1301.         *param = save_c;
  1302.         input_line_pointer = saveptr;
  1303.         return(NULL);
  1304.         }
  1305.         if(val >= (1 << format->ops[parcnt].width) || val < 0){
  1306.         error_param_message = "Parameter error: expression out "
  1307.                       "of range (parameter %lu)";
  1308.         *param = save_c;
  1309.         input_line_pointer = saveptr;
  1310.         return(NULL);
  1311.         }
  1312.     }
  1313.     *param = save_c;
  1314.     input_line_pointer = saveptr;
  1315.  
  1316.     if(*param == '\0'){
  1317.         if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
  1318.         insn->opcode |= val << format->ops[parcnt].offset;
  1319.         return(param);
  1320.         }
  1321.         else
  1322.         return(NULL);
  1323.     }
  1324.     else if(*param == ','){
  1325.         if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
  1326.         insn->opcode |= val << format->ops[parcnt].offset;
  1327.         return(param+1);
  1328.         }
  1329.         else
  1330.         return(NULL);
  1331.     }
  1332.     return(NULL);
  1333. }
  1334.  
  1335. static
  1336. char *
  1337. parse_num(
  1338. char *param,
  1339. struct m98k_insn *insn,
  1340. struct m98k_opcode *format,
  1341. unsigned long parcnt,
  1342. long max_width_zero)
  1343. {
  1344.     int val;
  1345.     char *saveptr, save_c;
  1346.     expressionS exp;
  1347.     segT seg;
  1348.  
  1349.     saveptr = input_line_pointer;
  1350.     input_line_pointer = param;
  1351.     while(*param != ',' && *param != '\0')
  1352.         param++;
  1353.     save_c = *param;
  1354.     *param = '\0';
  1355.     seg = expression(&exp);
  1356.     try_to_make_absolute(&exp);
  1357.     seg = exp.X_seg;
  1358.     *param = save_c;
  1359.     input_line_pointer = saveptr;
  1360.  
  1361.     val = exp.X_add_number;
  1362.     if(seg != SEG_ABSOLUTE){
  1363.         error_param_message = "Parameter error: expression must be "
  1364.                   "absolute (parameter %lu)";
  1365.         return(NULL);
  1366.     }
  1367.     if(max_width_zero){
  1368.         if(val == (1 << format->ops[parcnt].width))
  1369.         val = 0;
  1370.     }
  1371.     if(val >= (1 << format->ops[parcnt].width) || val < 0){
  1372.         error_param_message = "Parameter error: expression out "
  1373.                   "of range (parameter %lu)";
  1374.         return(NULL);
  1375.     }
  1376.  
  1377.     if(*param == '\0'){
  1378.         if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
  1379.         insn->opcode |= val << format->ops[parcnt].offset;
  1380.         return(param);
  1381.         }
  1382.         else
  1383.         return(NULL);
  1384.     }
  1385.     else if(*param == ','){
  1386.         if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
  1387.         insn->opcode |= val << format->ops[parcnt].offset;
  1388.         return(param+1);
  1389.         }
  1390.         else
  1391.         return(NULL);
  1392.     }
  1393.     return(NULL);
  1394.  
  1395. }
  1396.  
  1397. static
  1398. char *
  1399. parse_sh(
  1400. char *param,
  1401. struct m98k_insn *insn,
  1402. struct m98k_opcode *format,
  1403. unsigned long parcnt)
  1404. {
  1405.     int val;
  1406.     char *saveptr, save_c;
  1407.     expressionS exp;
  1408.     segT seg;
  1409.  
  1410.     saveptr = input_line_pointer;
  1411.     input_line_pointer = param;
  1412.     while(*param != ',' && *param != '\0')
  1413.         param++;
  1414.     save_c = *param;
  1415.     *param = '\0';
  1416.     seg = expression(&exp);
  1417.     try_to_make_absolute(&exp);
  1418.     seg = exp.X_seg;
  1419.     *param = save_c;
  1420.     input_line_pointer = saveptr;
  1421.  
  1422.     val = exp.X_add_number;
  1423.     if(seg != SEG_ABSOLUTE){
  1424.         error_param_message = "Parameter error: expression must be "
  1425.                   "absolute (parameter %lu)";
  1426.         return(NULL);
  1427.     }
  1428.     if(val == 64)
  1429.         val = 0;
  1430.     if(val >= 64 || val < 0){
  1431.         error_param_message = "Parameter error: expression out "
  1432.                   "of range (parameter %lu)";
  1433.         return(NULL);
  1434.     }
  1435.  
  1436.     if(*param == '\0'){
  1437.         if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
  1438.         insn->opcode |= (val & 0x1f) << 11;
  1439.         insn->opcode |= ((val >> 5) & 0x1) << 1;
  1440.         return(param);
  1441.         }
  1442.         else
  1443.         return(NULL);
  1444.     }
  1445.     else if(*param == ','){
  1446.         if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
  1447.         insn->opcode |= (val & 0x1f) << 11;
  1448.         insn->opcode |= ((val >> 5) & 0x1) << 1;
  1449.         return(param+1);
  1450.         }
  1451.         else
  1452.         return(NULL);
  1453.     }
  1454.     return(NULL);
  1455.  
  1456. }
  1457.  
  1458. static
  1459. char *
  1460. parse_mb(
  1461. char *param,
  1462. struct m98k_insn *insn,
  1463. struct m98k_opcode *format,
  1464. unsigned long parcnt)
  1465. {
  1466.     int val;
  1467.     char *saveptr, save_c;
  1468.     expressionS exp;
  1469.     segT seg;
  1470.  
  1471.     saveptr = input_line_pointer;
  1472.     input_line_pointer = param;
  1473.     while(*param != ',' && *param != '\0')
  1474.         param++;
  1475.     save_c = *param;
  1476.     *param = '\0';
  1477.     seg = expression(&exp);
  1478.     try_to_make_absolute(&exp);
  1479.     seg = exp.X_seg;
  1480.     *param = save_c;
  1481.     input_line_pointer = saveptr;
  1482.  
  1483.     val = exp.X_add_number;
  1484.     if(seg != SEG_ABSOLUTE){
  1485.         error_param_message = "Parameter error: expression must be "
  1486.                   "absolute (parameter %lu)";
  1487.         return(NULL);
  1488.     }
  1489.     if(val > 64 || val < 0){
  1490.         error_param_message = "Parameter error: expression out "
  1491.                   "of range (parameter %lu)";
  1492.         return(NULL);
  1493.     }
  1494.  
  1495.     if(*param == '\0'){
  1496.         if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
  1497.         insn->opcode |= (val & 0x1f) << 6;
  1498.         insn->opcode |= ((val >> 5) & 0x1) << 5;
  1499.         return(param);
  1500.         }
  1501.         else
  1502.         return(NULL);
  1503.     }
  1504.     else if(*param == ','){
  1505.         if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
  1506.         insn->opcode |= (val & 0x1f) << 6;
  1507.         insn->opcode |= ((val >> 5) & 0x1) << 5;
  1508.         return(param+1);
  1509.         }
  1510.         else
  1511.         return(NULL);
  1512.     }
  1513.     return(NULL);
  1514.  
  1515. }
  1516.  
  1517. /*
  1518.  * md_number_to_chars() is the target machine dependent routine that puts out
  1519.  * a binary value of size 4, 2, or 1 bytes into the specified buffer.  This is
  1520.  * done in the target machine's byte sex.  In this case the byte order is
  1521.  * big endian.
  1522.  */
  1523. void
  1524. md_number_to_chars(
  1525. char *buf,
  1526. long val,
  1527. int nbytes)
  1528. {
  1529.     switch(nbytes){
  1530.     case 4:
  1531.         *buf++ = val >> 24;
  1532.         *buf++ = val >> 16;
  1533.     case 2:
  1534.         *buf++ = val >> 8;
  1535.     case 1:
  1536.         *buf = val;
  1537.         break;
  1538.  
  1539.     default:
  1540.         abort();
  1541.     }
  1542. }
  1543.  
  1544. /*
  1545.  * md_number_to_imm() is the target machine dependent routine that puts out
  1546.  * a binary value of size 4, 2, or 1 bytes into the specified buffer with
  1547.  * reguard to a possible relocation entry (the fixP->fx_r_type field in the fixS
  1548.  * structure pointed to by fixP) for the section with the ordinal nsect.  This
  1549.  * is done in the target machine's byte sex using it's relocation types.
  1550.  * In this case the byte order is big endian.
  1551.  */
  1552. void
  1553. md_number_to_imm(
  1554. unsigned char *buf,
  1555. long val,
  1556. int nbytes,
  1557. fixS *fixP,
  1558. int nsect)
  1559. {
  1560.     unsigned long opcode;
  1561.  
  1562.     if(fixP->fx_r_type == NO_RELOC ||
  1563.        fixP->fx_r_type == M98K_RELOC_VANILLA){
  1564.         switch(nbytes){
  1565.         case 4:
  1566.         *buf++ = val >> 24;
  1567.         *buf++ = val >> 16;
  1568.         case 2:
  1569.         *buf++ = val >> 8;
  1570.         case 1:
  1571.         *buf = val;
  1572.         break;
  1573.  
  1574.         default:
  1575.         abort();
  1576.         }
  1577.         return;
  1578.     }
  1579.     switch(fixP->fx_r_type){
  1580.     case M98K_RELOC_HI16:
  1581.         buf[2] = val >> 24;
  1582.         buf[3] = val >> 16;
  1583.         break;
  1584.  
  1585.     case M98K_RELOC_LO16:
  1586.         buf[2] = val >> 8;
  1587.         buf[3] = val;
  1588.         break;
  1589.  
  1590.     case M98K_RELOC_HA16:
  1591.         val += 0x00008000;
  1592.         buf[2] = val >> 24;
  1593.         buf[3] = val >> 16;
  1594.         break;
  1595.  
  1596.     case M98K_RELOC_LO14:
  1597.         buf[2] = val >> 8;
  1598.         buf[3] = val & 0xfc;
  1599.         break;
  1600.  
  1601.     case M98K_RELOC_BR14:
  1602.         if((val & 0x00008000) != 0){
  1603.         opcode = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
  1604.         if(((opcode) & 0x03e00000) != 0x02800000){
  1605.             opcode ^= Y_BIT;
  1606.             buf[0] = opcode >> 24;
  1607.             buf[1] = opcode >> 16;
  1608.             buf[2] = opcode >> 8;
  1609.             buf[3] = opcode;
  1610.         }
  1611.         }
  1612.         if(fixP->fx_pcrel)
  1613.         val += 4;
  1614.         buf[2] = val >> 8;
  1615.         buf[3] |= val & 0xfc;
  1616.         break;
  1617.  
  1618.     case M98K_RELOC_BR24:
  1619.         if(fixP->fx_pcrel)
  1620.         val += 4;
  1621.         buf[0] |= (val >> 24) & 0x03;
  1622.         buf[1] = val >> 16;
  1623.         buf[2] = val >> 8;
  1624.         buf[3] |= val & 0xfc;
  1625.         break;
  1626.  
  1627.     default:
  1628.         as_warn("Bad relocation type");
  1629.         break;
  1630.     }
  1631. }
  1632.  
  1633. /*
  1634.  * md_atof() turns a string pointed to by input_line_pointer into a floating
  1635.  * point constant of type type, and store the appropriate bytes in *litP.
  1636.  * The number of LITTLENUMS emitted is stored indirectly through *sizeP.
  1637.  * An error message is returned, or a string containg only a '\0' for OK.
  1638.  * For this machine only IEEE single and IEEE double floating-point formats
  1639.  * are allowed.
  1640.  */
  1641. char *
  1642. md_atof(
  1643. int type,
  1644. char *litP,
  1645. int *sizeP)
  1646. {
  1647.     int    prec;
  1648.     LITTLENUM_TYPE words[6];
  1649.     LITTLENUM_TYPE *wordP;
  1650.     char *t;
  1651.  
  1652.     switch(type){
  1653.     case 'f':
  1654.     case 'F':
  1655.     case 's':
  1656.     case 'S':
  1657.         prec = 2;
  1658.         break;
  1659.  
  1660.     case 'd':
  1661.     case 'D':
  1662.     case 'r':
  1663.     case 'R':
  1664.         prec = 4;
  1665.         break;
  1666.  
  1667.     default:
  1668.         *sizeP = 0;
  1669.         return("Bad call to MD_ATOF()");
  1670.     }
  1671.     t = atof_ieee(input_line_pointer, type, words);
  1672.     if(t != NULL)
  1673.         input_line_pointer = t;
  1674.  
  1675.     *sizeP = prec * sizeof(LITTLENUM_TYPE);
  1676.     for(wordP = words; prec--; ){
  1677.         md_number_to_chars(litP, (long)(*wordP++), sizeof(LITTLENUM_TYPE));
  1678.         litP += sizeof(LITTLENUM_TYPE);
  1679.     }
  1680.     return ""; /* OK */
  1681. }
  1682.  
  1683. int
  1684. md_estimate_size_before_relax(
  1685. fragS *fragP,
  1686. int segment_type)
  1687. {
  1688.     as_warn("Relaxation should never occur");
  1689.     return(sizeof(long));
  1690. }
  1691.  
  1692. const relax_typeS md_relax_table[] = {0};
  1693.  
  1694. void
  1695. md_convert_frag(
  1696. fragS *fragP)
  1697. {
  1698.     as_warn("Relaxation should never occur");
  1699. }
  1700.